package com.rxyb.auth.config;

import cn.hutool.json.JSONUtil;
import com.rxyb.auth.feign.user.UserFeignServer;
import com.rxyb.auth.model.SecurityRole;
import com.rxyb.auth.model.SecurityUser;
import com.rxyb.auth.pojo.user.LoginReq;
import com.rxyb.auth.pojo.user.LoginRoleRsp;
import com.rxyb.auth.pojo.user.LoginRsp;
import com.rxyb.core.respone.R;
import com.rxyb.security.exception.BusiOAuth2Exception;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import java.util.ArrayList;
import java.util.List;

/**
 * @author YJH
 * @version 1.0
 * @description Security 验证
 * @date 2020/5/20  14:19
 */
@Configuration
@EnableWebSecurity
@Slf4j
@Order(90)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    // user信息
    private final UserFeignServer userFeignServer;
//    @Autowired(required = false)
//    private UrlRolesFilterHandler urlRolesFilterHandler;

    /**
     * Creates an instance with the default configuration enabled.
     */
    public SecurityConfiguration(UserFeignServer userFeignServer) {
        this.userFeignServer = userFeignServer;
    }

    @Bean
    @Override
    protected UserDetailsService userDetailsService() {
        return username -> {
            if (null == username || username.trim().length() <= 0) {
                throw new BusiOAuth2Exception("用户名为空");
            }
            LoginReq req = new LoginReq();
            req.setLoginName(username);
            R<LoginRsp> r = userFeignServer.login(req);
            log.debug("查询用户:[{}] 登录信息==>[{}]", username, JSONUtil.toJsonStr(r));

            if (!r.ok()) {
                throw new BusiOAuth2Exception(r.getMsg());
            }
            LoginRsp rsp = r.getData();
            SecurityUser user = new SecurityUser(rsp.getLoginName(), rsp.getLoginPwd());
            List<SecurityRole> sysRoleList = new ArrayList<>();
            for (LoginRoleRsp record : rsp.getRoleList()) {
                SecurityRole role = new SecurityRole();
                BeanUtils.copyProperties(record, role);
            }
            user.setSysRoleList(sysRoleList);
            return user;
        };
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().authenticated().and().formLogin().loginPage("/login").failureUrl("/login-error").permitAll();
        // 退出登录 缓存失效
        http.logout().invalidateHttpSession(true).permitAll();
        http.cors().disable();
        //
        //        /* 开启跨域共享，  跨域伪造请求限制=无效 */
        //        http.cors().and().csrf().disable();
        //
        /* 开启授权认证 */
        //        http.authorizeRequests()
        //                /* 动态url权限 */.withObjectPostProcessor(new DefinedObjectPostProcessor())
        //                /* url决策 */.accessDecisionManager(accessDecisionManager()).anyRequest().authenticated();
        //
        //        /* 登录配置 */
        //        http.formLogin().usernameParameter("username").passwordParameter("password").loginProcessingUrl("/login");
        //
        //        /* 登录失败后的处理 */
        //        http.formLogin().failureHandler(new LoginFailureHandler());
        //
        //        /* 登录过期/未登录 处理 */
        //        http.exceptionHandling().authenticationEntryPoint(new LoginExpireHandler());
        //
        //        /* 权限不足(没有赋予角色) 处理 */
        //        http.exceptionHandling().accessDeniedHandler(new AuthLimitHandler());
        //
        //        /* 登录成功后的处理 */
        //        http.formLogin().successHandler(new LoginSuccessHandler());
        //
        //        /* 退出成功处理器 */
        //        http.logout().logoutUrl("/logout").permitAll().invalidateHttpSession(true).logoutSuccessHandler(new LogoutHandler());

    }

    //    class DefinedObjectPostProcessor implements ObjectPostProcessor<FilterSecurityInterceptor> {
    //        @Override
    //        public <O extends FilterSecurityInterceptor> O postProcess(O object) {
    //            object.setSecurityMetadataSource(urlRolesFilterHandler);
    //            return object;
    //        }
    //    }

    /**
     * AffirmativeBased – 任何一个AccessDecisionVoter返回同意则允许访问
     * ConsensusBased – 同意投票多于拒绝投票（忽略弃权回答）则允许访问
     * UnanimousBased – 每个投票者选择弃权或同意则允许访问
     * <p>
     * 决策管理
     */
    //    private AccessDecisionManager accessDecisionManager() {
    //        List<AccessDecisionVoter<? extends Object>> decisionVoters = new ArrayList<>();
    //        decisionVoters.add(new WebExpressionVoter());
    //        decisionVoters.add(new AuthenticatedVoter());
    //        decisionVoters.add(new RoleVoter());
    //        /* 路由权限管理 */
    //        decisionVoters.add(new UrlRoleAuthHandler());
    //        return new UnanimousBased(decisionVoters);
    //    }
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        AuthenticationManager manager = super.authenticationManagerBean();
        return manager;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService()).passwordEncoder(new BCryptPasswordEncoder());
    }

    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
